﻿package
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.ObjectEncoding;
	import flash.net.Socket;
	import flash.utils.ByteArray;

	public class GameSocket extends EventDispatcher
	{                
		private var _socket:Socket;                        
		private var _host:String;
		private var _port:int;                
		
		private var _outbuffer:ByteArray;//输出缓冲器
		private var _inbuffer:ByteArray;//接收缓冲器                
		private var _outdataBytes:ByteArray;//Out的数据内容字节
		
		private var _isReadHead:Boolean = false;//是否读取了头部
		private var _headerBytes:ByteArray;//存储头部信息的字节
		private var _msglen:int = 0;//信息长度                                
		
		/**
		 * 是否连接
		 */
		public var IsConnect:Boolean;
		
		public function GameSocket(host:String,port:int) 
		{                                                
			//--------初始化各项参数--------
			this._host = host;
			this._port = port;
			this._socket = new Socket(this._host, this._port);                
			this._socket.objectEncoding = ObjectEncoding.AMF3;
			
			//--------缓冲器-----------
			this._inbuffer = new ByteArray();
			this._inbuffer.objectEncoding  = ObjectEncoding.AMF3;
			this._inbuffer.position = 0;
			
			this._outdataBytes = new ByteArray();
			this._outdataBytes.objectEncoding = ObjectEncoding.AMF3;
			
			this._outbuffer = new ByteArray();
			this._outbuffer.objectEncoding  = ObjectEncoding.AMF3;
			this._outbuffer.position = 0;
			
			this._headerBytes = new ByteArray();
			
			//--------添加事件监听----------
			this._socket.addEventListener(Event.CONNECT, this._connectHandler);            
			this._socket.addEventListener(Event.CLOSE, this._closeHandler);   
			this._socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this._securityError);
			this._socket.addEventListener(IOErrorEvent.IO_ERROR, this._ioErrorHandler);   
			this._socket.addEventListener(ProgressEvent.SOCKET_DATA, this._dataHandler); 
		}
		
		//成功连接
		private function _connectHandler(evt:Event):void
		{
			this.IsConnect = true;
		}
		
		//关闭连接
		private function _closeHandler(evt:Event):void
		{
			this.IsConnect = false;
		}
		
		//未通过安全验证
		private function _securityError(evt:Event):void
		{
		}
		
		//数据传输错误
		private function _ioErrorHandler(evt:Event):void
		{
		}
		
		
		/**
		 * 接收到数据
		 * @param        evt
		 */                
		private function _dataHandler(evt:Event):void
		{                        
			try
			{        
				this.readData();
			}
			catch (e:Error) 
			{
				//--------------
			}                        
			finally {        
				this._inbuffer.length = 0;//清除缓冲区
			}                
		}
		
		//************************************************************
		
		/**
		 * 读取数据
		 */
		private function readData():void
		{
			//如果还没读过头部则读一次。
			if (!this._isReadHead && this._socket.bytesAvailable > 4)
			{
				this._headerBytes.length = 0;
				this._headerBytes.position = 0;
				this._socket.readBytes(this._headerBytes, 0, 4);
				this._msglen = this._headerBytes.readInt();
				//trace("新的消息长度:" + this.msgLen);
				this._isReadHead = true;
			}
			//如果读了头部，并且当前可读长度大于等于消息长度，则开始读取
			if (this._isReadHead && this._socket.bytesAvailable >= this._msglen)
			{
				this._inbuffer.length = 0;                
				this._inbuffer.position  = 0;
				this._socket.readBytes(_inbuffer, 0, this._msglen); 
				this._isReadHead = false;
				
				//读完了，可以去解释了  
				我的对象 = this._inbuffer.readObject();
			} 
			
			//如果是读过头，则如果当前消息大于消息长度则再次调用读取，否则则判断是否可读头部
			if (this._socket.bytesAvailable > 0 && !this._isReadHead)
				this.readData();
		}
		//************************************************************
		
		
		/**
		 * 启动连接
		 */
		public function StartConn():void
		{
			this._socket.connect(this._host,this._port);
		}
		
		/**
		 * 关闭连接
		 */
		public function CloseConn():void
		{
			this.socket.close();
		}
		
		/**
		 * 发送数据
		 * @param        o        发送的数据包结构
		 */
		public function Send(o:我的对象):Boolean
		{                        
			//数据字节
			this._outdataBytes.length = 0;
			this._outdataBytes.position = 0;
			this._outdataBytes.writeObject(o);
			
			//输出缓存初始化
			this._outbuffer.length = 0;
			this._outbuffer.position = 0;
			
			//写入输出字节长度（Header）
			this._outbuffer.writeInt(this._outdataBytes.length);
			
			//写入数据字节到输出缓存
			this._outbuffer.writeBytes(this._outdataBytes, 0, this._outdataBytes.length);                            
			
			this._socket.writeBytes(this._outbuffer);
			this._socket.flush();           
			
			return true;
		}
		
		
		public function get socket():Socket { return _socket; }
	}
	
	
}

